package com.sfddata.musicpillow.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sfddata.musicpillow.common.utils.MyUtils;
import com.sfddata.musicpillow.user.entity.*;
import com.sfddata.musicpillow.user.service.MonthReportInfoService;
import com.sfddata.musicpillow.user.service.ReportService;
import com.sfddata.musicpillow.user.service.TbSleepRecordService;
import com.sfddata.musicpillow.user.service.WeekReportInfoService;
import jdk.nashorn.internal.runtime.logging.Logger;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Logger
public class ReportServiceImpl implements ReportService {

    @Autowired
    TbSleepRecordService tbSleepRecordService;

    @Autowired
    WeekReportInfoService weekReportInfoService;

    @Autowired
    MonthReportInfoService monthReportInfoService;
    @Override
    public MonthReportInfoVo getMonthReport(Long userId, String date) throws ParseException {

        DateVo countDate = countFirstDayOfMonth(date);
        ArrayList<TbSleepRecordEntity> weekRecords = tbSleepRecordService.getWeekRecordBeginDate(userId, countDate);

        if (weekRecords == null){
            return null;
        }
        // 计算统计数据
        WeekReportInfoVo wvo = countStatisticsData(weekRecords, userId);
        MonthReportInfoVo mvo = new MonthReportInfoVo();
        MonthReportInfo m = new MonthReportInfo();
        WeekReportInfo w = copyVoToEntity(wvo);
        BeanUtils.copyProperties(wvo, mvo);
        BeanUtils.copyProperties(w, m);
        // 入库
        QueryWrapper<MonthReportInfo> qw = new QueryWrapper<>();
        qw.eq("user_id", userId);
        qw.eq("start_day", m.getStartDay());

        MonthReportInfo one = monthReportInfoService.getOne(qw);
        if (one == null){
            monthReportInfoService.save(m);
        }else {
            m.setId(one.getId());
            monthReportInfoService.update(m, qw);
        }
        // 查询上一次的记录 然后填入对比数据
        QueryWrapper<MonthReportInfo> qw2 = new QueryWrapper<>();
        qw2.eq("user_id", userId);
        qw2.lt("start_day", m.getStartDay());
        qw2.orderByDesc("start_day");
        List<MonthReportInfo> list = monthReportInfoService.list(qw2);

        if (list.size() != 0){
            MonthReportInfo oldm = list.get(0);
            mvo.setCompareAhi((m.getAvgAhi() - oldm.getAvgAhi()));
            mvo.setCompareAsleep((m.getAvgAsleep() - oldm.getAvgAsleep()));
            mvo.setCompareDeepSleep((m.getAvgDeepSleep() - oldm.getAvgDeepSleep()));
            mvo.setCompareSleepScore((m.getAvgSleepScore() - oldm.getAvgSleepScore()));
            mvo.setCompareSnore((m.getAvgSnore() - oldm.getAvgSnore()));
            System.out.println("11111111111");
            System.out.println(m.getAvgSnore());
            System.out.println(oldm.getAvgSnore());
            System.out.println(m.getAvgSnore() - oldm.getAvgSnore());
            System.out.println("11111111111");
            mvo.setCompareSleepTime((m.getAvgSleepTime() - oldm.getAvgSleepTime()));
        }

        return mvo;
    }


    @Override
    public WeekReportInfoVo getWeekReport(Long userId, String date) throws ParseException {


        DateVo countDate = countFirstDayOfWeek(date);
        ArrayList<TbSleepRecordEntity> weekRecords = tbSleepRecordService.getWeekRecordBeginDate(userId, countDate);

        if (weekRecords == null){
            return null;
        }

        WeekReportInfoVo vo = countStatisticsData(weekRecords, userId);
        WeekReportInfo weekReportInfo = copyVoToEntity(vo);

        QueryWrapper<WeekReportInfo> weekReportInfoQueryWrapper = new QueryWrapper<>();
        weekReportInfoQueryWrapper.eq("user_id", userId);
        weekReportInfoQueryWrapper.eq("start_day", weekReportInfo.getStartDay());
        weekReportInfoService.saveOrUpdate(weekReportInfo, weekReportInfoQueryWrapper);

        WeekReportInfo one = weekReportInfoService.getOne(weekReportInfoQueryWrapper);
        if (one == null){
            weekReportInfoService.save(weekReportInfo);
        }else {
            weekReportInfo.setId(one.getId());
            weekReportInfoService.update(weekReportInfo, weekReportInfoQueryWrapper);
        }

        // 查询上一次的记录 然后填入对比数据
        QueryWrapper<WeekReportInfo> qw2 = new QueryWrapper<>();
        qw2.eq("user_id", userId);
        qw2.lt("start_day", weekReportInfo.getStartDay());
        qw2.orderByDesc("start_day");
        List<WeekReportInfo> list = weekReportInfoService.list(qw2);

        if (list.size() != 0){
            WeekReportInfo oldw = list.get(0);
            vo.setCompareSleepTime(weekReportInfo.getAvgSleepTime() - oldw.getAvgSleepTime());
            vo.setCompareAhi(weekReportInfo.getAvgAhi() - oldw.getAvgAhi());
            vo.setCompareAsleep(weekReportInfo.getAvgAsleep() - oldw.getAvgAsleep());
            vo.setCompareDeepSleep(weekReportInfo.getAvgDeepSleep() - oldw.getAvgDeepSleep());
            vo.setCompareSleepScore(weekReportInfo.getAvgSleepScore() - oldw.getAvgSleepScore());
            vo.setCompareSnore(weekReportInfo.getAvgSnore() - oldw.getAvgSnore());
        }
        return vo;
    }

    private WeekReportInfo copyVoToEntity(WeekReportInfoVo vo) throws ParseException {


        WeekReportInfo weekReportInfo = new WeekReportInfo(
                vo.getUserId().toString(),
                vo.getStartDay(),
                null,
                vo.getSleepScoreTable(),
                vo.getAvgSleepScore(),
                vo.getSleepTimeTable(),
                vo.getAvgSleepTime(),
                vo.getAsleepTimeTable(),
                vo.getAsleepTable(),
                vo.getAvgAsleep(),
                vo.getDeepSleepTable(),
                vo.getAvgDeepSleep(),
                vo.getSnoreTable(), vo.getAvgSnore(), vo.getAhiTable(),
                vo.getAvgAhi());
        return weekReportInfo;

    }

    /**
     * week和month的report数据是一一样的 所以都拿weekdata返回 再copy就行
     *
     * 有问题:如果是周报 没有数据的日子 应该填0
     *
     *
     *
     * @param weekRecords
     * @return
     */
    private WeekReportInfoVo countStatisticsData(ArrayList<TbSleepRecordEntity> weekRecords, Long uid) throws ParseException {

        List<String> scoreList = new ArrayList<>();
        List<String> durationList = new ArrayList<>();
        List<String> aSleeplist = new ArrayList<>();
        List<String> awakeList = new ArrayList<>();
        List<String> deepList = new ArrayList<>();
        List<String> snoreList = new ArrayList<>();
        List<String> AHIList = new ArrayList<>();

        int num = 0;
        Float scoreSum = 0F;
        Float durationSum = 0F;
        Float aSleepSum = 0F;
        Float awakeSum = 0F;
        Float deepSum = 0F;
        Float snoreSum = 0F;
        Float AHISum = 0F;

        for (TbSleepRecordEntity record : weekRecords) {

            if (record.getId() == null){
                scoreList.add("-1");
                durationList.add("-1");
                aSleeplist.add("-1");
                awakeList.add("-1");
                deepList.add("-1");
                snoreList.add("-1");
                AHIList.add("-1");
                continue;
            }

            scoreList.add(record.getColScore());
            durationList.add(record.getColSleepDuration());
            aSleeplist.add(record.getColAsleepTime() + "-" + record.getColEndSleepTime());
            awakeList.add(record.getColAwakeDuration());
            deepList.add(record.getColDeepDuration());
            snoreList.add(record.getSnoreTime());

            // 呼吸暂停列表
            String apneaListString = record.getApneaList();
            List<Integer> apneaList = new ArrayList<>();
            if (apneaListString != null && !apneaListString.equals("[]")){
                // 去掉首位的括号 然后按，分割 再转为数字
                apneaList = Arrays.stream(apneaListString.substring(1, apneaListString.length() - 1)
                        .split(","))
                        .map(s -> Integer.parseInt(s.trim()))
                        .collect(Collectors.toList());
            }

            long count = apneaList.stream().filter(
                    i -> {
                return i > 0;
            }).count();

            BigDecimal countDecimal = new BigDecimal(count);
            BigDecimal bigDecimal = new BigDecimal(record.getColSleepDuration());
            BigDecimal sixDecimal = new BigDecimal(60);
            // 他们给我的ahi算法/
            BigDecimal ahi;
            if (!bigDecimal.equals(0)){
                ahi = countDecimal.divide(bigDecimal.divide(sixDecimal, 2, BigDecimal.ROUND_HALF_UP), 2, BigDecimal.ROUND_HALF_UP);
            }else {
                ahi = BigDecimal.valueOf(0);
            }
            System.out.println(ahi);
            AHIList.add(String.valueOf(ahi));
            num++;

            scoreSum += Float.parseFloat(record.getColScore());
            durationSum += Float.parseFloat(record.getColSleepDuration());
            awakeSum += Float.parseFloat(record.getColAwakeDuration());
            deepSum += Float.parseFloat(record.getColDeepDuration());
            snoreSum += Float.parseFloat(record.getSnoreTime());
            AHISum += ahi.longValue();

        }

        Float scoreAvg = scoreSum /num;
        Float durationAvg = durationSum /num;
        Float awakeAvg = awakeSum /num;
        Float deepAvg = deepSum /num;
        Float snoreAvg = snoreSum /num;
        Float AHIAvg = AHISum /num;

        return new WeekReportInfoVo(uid.toString(), weekRecords.get(0).getColDate(), weekRecords.get(weekRecords.size() - 1).getColDate(),
                scoreList, scoreAvg, durationList, durationAvg, aSleeplist, awakeList, awakeAvg, deepList, deepAvg, snoreList, snoreAvg, AHIList, AHIAvg);

    }

    private DateVo countFirstDayOfWeek(String date) throws ParseException {

        Date parse;
        DateVo dateVo = new DateVo();

        parse = new SimpleDateFormat("yyyy-MM-dd").parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse);
        int weekDay = calendar.get(Calendar.DAY_OF_WEEK);
        int mins = weekDay == 1 ? 6 : weekDay - 2;

        if(mins > 0) {
            calendar.add(Calendar.DATE, -mins);
        }

        dateVo.setFirstDay(calendar.getTime());
        calendar.add(Calendar.DATE, 6);
        dateVo.setLastDay(calendar.getTime());
        return dateVo;
    }

    private DateVo countFirstDayOfMonth(String date) throws ParseException {

        Date parse;
        DateVo dateVo = new DateVo();
        parse = new SimpleDateFormat("yyyy-MM-dd").parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse);

       ;// 这个月的第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        dateVo.setFirstDay(calendar.getTime());
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        dateVo.setLastDay(calendar.getTime());

        return dateVo;
    }
}
